﻿using LiveCharts;
using LiveCharts.Wpf;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using UIWindow.Domains;
using UIWindow.Entitys;
using UIWindow.Enums;
using UIWindow.Helper;

namespace UIWindow.GlobalParameters
{
    [Attributes.Singleton]
    public class DataReportGlobal : INotifyPropertyChanged
    {
        #region 查询属性
        /// <summary>
        /// 开始时间
        /// </summary>
        public DateTime StartTime { get; set; }

        /// <summary>
        /// 结束时间
        /// </summary>
        public DateTime EndTime { get; set; }
        /// <summary>
        /// 批次号
        /// </summary>
        public string ProductModel { get; set; }
        /// <summary>
        /// 班次
        /// </summary>
        public string Shift { get; set; }
        #endregion
        #region 本月总量
        private int _totalProduction;
        /// <summary>
        /// 生产总量
        /// </summary>
        public int TotalProduction { get; set; }
        /// <summary>
        /// 生产良率
        /// </summary>
        public double ProductionYield { get; set; }
        /// <summary>
        /// OK总量
        /// </summary>
        public int OKTotal { get; set; }
        /// <summary>
        /// NG总量
        /// </summary>
        public int NGTotal { get; set; }
        #endregion
        #region NG总量
        private int _scanCodeNG;
        /// <summary>
        /// 扫码NG
        /// </summary>
        public int ScanCodeNG { get; set; }
        /// <summary>
        /// MESNG
        /// </summary>
        public int MESNG { get; set; }
        /// <summary>
        /// 短路测试NG
        /// </summary>
        public int ShortCircuitNG { get; set; }
        /// <summary>
        /// 称重NG
        /// </summary>
        public int WeighingNG { get; set; }
        /// <summary>
        /// 注液NG
        /// </summary>
        public int LiquidInjectionNG { get; set; }
        /// <summary>
        /// 打胶钉NG
        /// </summary>
        public int CapNG { get; set; }
        #endregion
        #region 重量走势图
        public SeriesCollection WeightSeriesCollection { get; set; }
        public string[] WeightLabels { get; set; }
        public Func<double, string> WeightFormatter { get; set; }
        #endregion
        #region 注液走势图
        public SeriesCollection LiquidInjectionSeriesCollection { get; set; }
        public Func<double, string> LiquidInjectionXFormatter { get; set; }
        public Func<double, string> LiquidInjectionYFormatter { get; set; }
        #endregion
        #region 饼状图
        public SeriesCollection PieSeries { get; set; }
        public Func<double, string> PieFormatter { get; set; }
        public event PropertyChangedEventHandler PropertyChanged;
        public ZoomingOptions ZoomingMode { get; set; }
        #endregion
        public AsyncObservableCollection<ProductionData> WeightList { get; set; }
        public DataReportGlobal()
        {
            StartTime = DateTime.Now.Date;
            EndTime = DateTime.Now.Date;
            WeightList = new AsyncObservableCollection<ProductionData>();
            #region 重量走势图
            WeightSeriesCollection = new SeriesCollection
            {
                new ColumnSeries
                {
                    Title = "前重",
                    Fill = new SolidColorBrush(Color.FromArgb(0xEE,0x66,0xCC,0xCC)),
                },
                new ColumnSeries
                {
                    Title = "后重",
                    Fill = new SolidColorBrush(Color.FromArgb(0xEE, 0x99, 0xCC, 0xFF)),
                    Stroke = new SolidColorBrush(Color.FromRgb(0x2d, 0xff, 0x70)),
                    StrokeThickness = 1,
                }
            };
            WeightFormatter = value => value.ToString("N");
            #endregion
            #region 注液量走势图
            LiquidInjectionXFormatter = val => new DateTime((long)val).ToString("dd MMM");
            LiquidInjectionYFormatter = val => val.ToString("0.00 g");
            var gradientBrush = new LinearGradientBrush
            {
                StartPoint = new Point(0, 0),
                EndPoint = new Point(0, 1)
            };
            gradientBrush.GradientStops.Add(new GradientStop(Color.FromRgb(0x2d, 0xff, 0x70), 0));
            gradientBrush.GradientStops.Add(new GradientStop(Colors.Transparent, 1));
            LiquidInjectionSeriesCollection = new SeriesCollection
            {
                new LineSeries
                {
                    Values = new ChartValues<double>(),
                    Fill = gradientBrush,
                    Stroke = new SolidColorBrush(Color.FromRgb(0x2d, 0xff, 0x70)),
                    StrokeThickness = 1,
                    PointGeometrySize = 0
                }
            };
            #endregion
            #region 饼状图
            PieFormatter = x => x.ToString("N1");
            ZoomingMode = ZoomingOptions.X;
            TotalProduction = 120;
            ScanCodeNG = 10;
            WeighingNG = 3;
            LiquidInjectionNG = 20;
            PieSeries = new SeriesCollection() {
                new PieSeries
                {
                    Title = "OK 总量",
                    FontSize = 20,
                    DataLabels = true,
                    LabelPoint = chartPoint => string.Format("{0}({1:p})", chartPoint.Y, chartPoint.Participation),
                    Values = new ChartValues<int>
                    {
                        TotalProduction
                    },
                    Fill = new SolidColorBrush(Color.FromArgb(0xEE, 0x2A, 0xF3, 0x73)),
                    PushOut = 5
                },
                new PieSeries
                {
                    Title = "扫码 NG",
                    FontSize = 15,
                     DataLabels = true,
                    LabelPoint = chartPoint => string.Format("{0}({1:p})", chartPoint.Y, chartPoint.Participation),
                    Values = new ChartValues<int>
                    {
                        ScanCodeNG
                    },
                },
                new PieSeries
                {
                    Title = "称重 NG",
                    DataLabels = true,
                    FontSize = 15,
                    LabelPoint = chartPoint => string.Format("{0}({1:p})", chartPoint.Y, chartPoint.Participation),
                    Values = new ChartValues<int>
                    {
                        WeighingNG
                    },
                },
                new PieSeries
                {
                    Values = new ChartValues<int>
                    {
                        MESNG
                    },
                    Title = "密封塞 NG",
                },
                //new PieSeries
                //{
                //    Values = new ChartValues<int>
                //    {
                //        ShortCircuitNG
                //    },
                //    Title = "短路测试",
                //},
                new PieSeries
                {
                    LabelPoint = chartPoint => string.Format("{0}({1:p})", chartPoint.Y, chartPoint.Participation),
                    FontSize = 15,
                    Title = "注液 NG",
                    DataLabels = true,
                    Values = new ChartValues<int>
                    {
                        LiquidInjectionNG
                    },
                },
                //new PieSeries
                //{
                //    Values = new ChartValues<int>
                //    {
                //        CapNG
                //    },
                //    Title = "打胶钉NG",
                //}
            };
            #endregion
            //GetData().ConfigureAwait(false);
        }

        private List<string> _weightLabelsList = new List<string>();
        /// <summary>
        /// 获取数据
        /// </summary>
        /// <returns></returns>
        public async Task GetData()
        {
            if (StartTime.Year != EndTime.Year)
            {
                "请选择同一年".MessageDialogs(Enums.MessageLevelType.Warning);
                return;
            }
            if (GetQuarterly(StartTime.Month) != GetQuarterly(EndTime.Month))
            {
                $"请选择季度查询\r\n一月到三月是一个季度\r\n四月到六月是一个季度\r\n7月至9月是一个季度\r\n十月至十二月是一个季度\r\n".MessageDialogs(Enums.MessageLevelType.Warning);
                return;
            }
            WeightList.Clear();
            await Task.Run(() =>
            {
                ProductionData.Meta.TableName = $"productiondata_{StartTime:yyyy}{StartTime.GetQuarterly()}";
                XCode.Expression expression = ProductionData._.FrontScanTime >= StartTime & ProductionData._.FrontScanTime <= EndTime.AddDays(1);
                if (!string.IsNullOrEmpty(ProductModel)) expression &= ProductionData._.ProductBatch == ProductModel;
                if (!string.IsNullOrEmpty(Shift)) expression &= ProductionData._.UserName == Shift;
                var list = ProductionData.FindAll(expression);
                if (list.Count == 0) return;
                foreach (var item in list)
                {
                    WeightList.Add(item);
                }
                while (list.Count != WeightList.Count)
                {
                    System.Threading.Thread.Sleep(5);
                }
                TotalProduction = WeightList.Count;
                ScanCodeNG = WeightList.Count(x => x.JudgementResultAfterWeighing == NGType.扫码NG);
                WeighingNG = WeightList.Count(x => x.JudgementResultForeweigh == NGType.前称重偏重 || x.JudgementResultForeweigh == NGType.前称重偏轻);
                //ShortCircuitNG = WeightList.Where(x => x.JudgementResultAfterWeighing == NGType.短路测试NG).Count();
                LiquidInjectionNG = WeightList.Count(x => x.JudgementResultAfterWeighing == NGType.注液偏多 || x.JudgementResultAfterWeighing == NGType.注液偏少);
                CapNG = WeightList.Count(x => x.JudgementResultAfterWeighing == NGType.密封塞偏低 || x.JudgementResultAfterWeighing == NGType.密封塞偏高);

                NGTotal = ScanCodeNG + WeighingNG + LiquidInjectionNG + CapNG;
                OKTotal = TotalProduction - NGTotal;
                PieSeries[0].Values[0] = TotalProduction;
                PieSeries[1].Values[0] = ScanCodeNG;
                PieSeries[2].Values[0] = WeighingNG;
                PieSeries[3].Values[0] = CapNG;
                PieSeries[4].Values[0] = LiquidInjectionNG;
                //PieSeries[4].Values[0] = ShortCircuitNG;
                //PieSeries[5].Values[0] = LiquidInjectionNG;
                WeightLabels = _weightLabelsList.ToArray();
                _weightLabelsList.Clear();
                Bootstrapper.UISynchronize(() =>
                {
                    ChartValues<double> one = new ChartValues<double>();
                    ChartValues<double> two = new ChartValues<double>();
                    ChartValues<double> three = new ChartValues<double>();
                    one.AddRange(WeightList.Skip(WeightList.Count - (WeightList.Count > 30 ? 30 : WeightList.Count)).Select(x => x.FluidRate).ToList());
                    two.AddRange(WeightList.Skip(WeightList.Count - (WeightList.Count > 30 ? 30 : WeightList.Count)).Select(x => x.Preweight).ToList());                                                                                                                                                                            //_weightLabelsList.AddRange((IEnumerable<string>)WeightList.Skip(WeightList.Count - 30).Select(x => x.BracketNumber).ToList());
                    three.AddRange(WeightList.Skip(WeightList.Count - (WeightList.Count > 30 ? 30 : WeightList.Count)).Select(x => x.Afterweight).ToList());
                    LiquidInjectionSeriesCollection[0].Values = one;
                    WeightSeriesCollection[0].Values = two;
                    WeightSeriesCollection[1].Values = three;
                });
            });
        }

        private int GetQuarterly(int count)
        {
            switch (count)
            {
                case int p when p >= 1 && p < 4:
                    return 1;
                case int p when p >= 4 && p < 7:
                    return 2;
                case int p when p >= 7 && p < 10:
                    return 3;
                case int p when p >= 10 && p <= 12:
                    return 4;
            }
            return 1;
        }
    }
}
